package textdiff {
	import mx.collections.ArrayCollection;
	

	/**
	 * Creates and holds a List of edit commands that can be used to tranform Old
	 * into New. The constructor does all the work. Use any methods of the ancestor
	 * ArrayList to access the commands. getCommand is a get wrapped to do the
	 * casting to EditCommand.
	 */
	public class Report extends ArrayCollection {
		
		public function Report() {
			super();
		}
		
	    /**
	     * Create a Report (list of edit commands) from old and new file info.
	     */
	    public function createReport(oldFileInfo: FileInfo, newFileInfo:FileInfo): void {
	    	this.removeAll();
            var oldLineInfo:LineInfo = oldFileInfo.currentLineInfo();
            var newLineInfo:LineInfo = newFileInfo.currentLineInfo();
	    	while (true) {
	            oldLineInfo = oldFileInfo.currentLineInfo();
	            newLineInfo = newFileInfo.currentLineInfo();
				if (oldLineInfo.isEOF() && newLineInfo.isEOF()) break;	
	            else if (oldLineInfo.isEOF() && newLineInfo.isNewOnly()) {
	                this.addItem( new AppendCommand( oldFileInfo, newFileInfo ) );
	            }
	            else if (oldLineInfo.isOldOnly() && newLineInfo.isNewOnly()) {
	                this.addItem( new ChangeCommand( oldFileInfo, newFileInfo ) );
	            }
	            else if (newLineInfo.isNewOnly()) {
	                this.addItem( new InsertCommand( oldFileInfo, newFileInfo ) );
	            }
	            else if (oldLineInfo.isOldOnly()) {
	                this.addItem( new DeleteCommand( oldFileInfo, newFileInfo ) );
	            }
	            else if (oldLineInfo.isMatch()) {
	                this.addItem( new MatchCommand( oldFileInfo, newFileInfo ) );
	            }
	            else if (newLineInfo.isMatch()) {
	                newFileInfo.nextBlock(); // discard
	            }
	        }
	    }
	    
	    public function toXML(): XML {
	    	var x:XML = <changes></changes>;
	    	for (var i:int; i<this.length; i++) {
	    		var ec:EditCommand = this.getItemAt(i) as EditCommand;
	    		if (!(ec is MatchCommand)) {
	    			x.appendChild(ec.toXML());
	    		}
	    	}
	    	return x;
	    }
	    
	    public function toEditScript():String {
	    	var commands:Array = this.toArray();//.sortOn("fromLineNum", Array.DESCENDING);
	    	var s:String = "";
	    	for (var i:int; i<commands.length; i++) {
	    		var ec:EditCommand = commands[i] as EditCommand;
	    		if (ec.command != "Match") {
	    			s += ec.toEditScript();
	    		}
	    	}
	    	return s;
	    }
	
	    public function getCommand(lineNum: int): EditCommand
	    {
	        return super.getItemAt(lineNum) as EditCommand;
	    }
	}
}